/*
 * @Author: 0x9DEFA478
 * @Date: 2021-08-14 17:19:35
 * @LastEditTime: 2024-07-26 20:54:48
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "H_FIFO.h"




extern H_FIFO_SizeType H_FIFO_byte_ReadSize(volatile void* Buffer,H_FIFO_SizeType Id);
extern void H_FIFO_byte_WriteSize(volatile void* Buffer,H_FIFO_SizeType Id,H_FIFO_SizeType Size);
extern void H_FIFO_byte_Copy(volatile void* Buffer,H_FIFO_SizeType Id,const volatile void* Src,H_FIFO_SizeType Size);
extern const void* H_FIFO_byte_GetPointer(volatile void* Buffer,H_FIFO_SizeType Id);

extern H_FIFO_SizeType H_FIFO_uint16_ReadSize(volatile void* Buffer,H_FIFO_SizeType Id);
extern void H_FIFO_uint16_WriteSize(volatile void* Buffer,H_FIFO_SizeType Id,H_FIFO_SizeType Size);
extern void H_FIFO_uint16_Copy(volatile void* Buffer,H_FIFO_SizeType Id,const volatile void* Src,H_FIFO_SizeType Size);
extern const void* H_FIFO_uint16_GetPointer(volatile void* Buffer,H_FIFO_SizeType Id);

extern H_FIFO_SizeType H_FIFO_uint32_ReadSize(volatile void* Buffer,H_FIFO_SizeType Id);
extern void H_FIFO_uint32_WriteSize(volatile void* Buffer,H_FIFO_SizeType Id,H_FIFO_SizeType Size);
extern void H_FIFO_uint32_Copy(volatile void* Buffer,H_FIFO_SizeType Id,const volatile void* Src,H_FIFO_SizeType Size);
extern const void* H_FIFO_uint32_GetPointer(volatile void* Buffer,H_FIFO_SizeType Id);

extern H_FIFO_SizeType H_FIFO_uint64_ReadSize(volatile void* Buffer,H_FIFO_SizeType Id);
extern void H_FIFO_uint64_WriteSize(volatile void* Buffer,H_FIFO_SizeType Id,H_FIFO_SizeType Size);
extern void H_FIFO_uint64_Copy(volatile void* Buffer,H_FIFO_SizeType Id,const volatile void* Src,H_FIFO_SizeType Size);
extern const void* H_FIFO_uint64_GetPointer(volatile void* Buffer,H_FIFO_SizeType Id);




/**
 * @brief 初始化FIFO
 * @param fifo 未使用过的FIFO句柄
 * @param Type FIFO输入/输出的数据类型 vH_FIFO_Type_byte vH_FIFO_Type_uint16 vH_FIFO_Type_uint32 vH_FIFO_Type_uint64
 * @param Buffer 指向用于缓存数据的内存的指针
 * @param BufferSize 缓存大小, 单位为Type指定的数据类型宽度
 * @return 无
 */
void H_FIFO_Init(H_FIFO* fifo,H_FIFO_SizeType Type,void* Buffer,H_FIFO_SizeType BufferSize){
  
  fifo->FIFO.InId=0;
  fifo->FIFO.OutId=0;

  fifo->FIFO.Buffer=Buffer;
  fifo->FIFO.BufferSize=BufferSize;

  switch(Type){
    case vH_FIFO_Type_byte:
    
#if   H_FIFO_SizeOfSizeType == 2
      fifo->FIFO.SizeSize=2;
#elif H_FIFO_SizeOfSizeType == 4
      fifo->FIFO.SizeSize=4;
#elif H_FIFO_SizeOfSizeType == 8
      fifo->FIFO.SizeSize=8;
#else
#error "请选择可用的位宽"
#endif

      fifo->ReadSize=H_FIFO_byte_ReadSize;
      fifo->WriteSize=H_FIFO_byte_WriteSize;
      fifo->Copy=H_FIFO_byte_Copy;
      fifo->GetPointer=H_FIFO_byte_GetPointer;
      break;
    case vH_FIFO_Type_uint16:

#if   H_FIFO_SizeOfSizeType == 2
      fifo->FIFO.SizeSize=1;
#elif H_FIFO_SizeOfSizeType == 4
      fifo->FIFO.SizeSize=2;
#elif H_FIFO_SizeOfSizeType == 8
      fifo->FIFO.SizeSize=4;
#else
#error "请选择可用的位宽"
#endif

      fifo->ReadSize=H_FIFO_uint16_ReadSize;
      fifo->WriteSize=H_FIFO_uint16_WriteSize;
      fifo->Copy=H_FIFO_uint16_Copy;
      fifo->GetPointer=H_FIFO_uint16_GetPointer;
      break;
    case vH_FIFO_Type_uint32:

#if   H_FIFO_SizeOfSizeType == 2
      fifo->FIFO.SizeSize=1;
#elif H_FIFO_SizeOfSizeType == 4
      fifo->FIFO.SizeSize=1;
#elif H_FIFO_SizeOfSizeType == 8
      fifo->FIFO.SizeSize=2;
#else
#error "请选择可用的位宽"
#endif

      fifo->ReadSize=H_FIFO_uint32_ReadSize;
      fifo->WriteSize=H_FIFO_uint32_WriteSize;
      fifo->Copy=H_FIFO_uint32_Copy;
      fifo->GetPointer=H_FIFO_uint32_GetPointer;
      break;
    case vH_FIFO_Type_uint64:

#if   H_FIFO_SizeOfSizeType == 2
      fifo->FIFO.SizeSize=1;
#elif H_FIFO_SizeOfSizeType == 4
      fifo->FIFO.SizeSize=1;
#elif H_FIFO_SizeOfSizeType == 8
      fifo->FIFO.SizeSize=1;
#else
#error "请选择可用的位宽"
#endif

      fifo->ReadSize=H_FIFO_uint64_ReadSize;
      fifo->WriteSize=H_FIFO_uint64_WriteSize;
      fifo->Copy=H_FIFO_uint64_Copy;
      fifo->GetPointer=H_FIFO_uint64_GetPointer;
      break;
    default:
      for(;;){
        //不支持的类型
      }
  }
}

/**
 * @brief FIFO是否为空
 * @param fifo FIFO句柄
 * @return 0:FIFO空 其他:FIFO不为空
 */
int H_FIFO_IsEmpty(H_FIFO* fifo){
  if(oH_FIFO_IsEmpty(fifo)){
    return -1;
  }

  return 0;
}

/**
 * @brief 获取FIFO的当前最大可写入长度
 * @param fifo FIFO句柄
 * @return 当前可写入的最大数据长度(以fifo输入的数据类型位宽为单位)
 */
H_FIFO_SizeType H_FIFO_GetEmptySize(H_FIFO* fifo){
  H_FIFO_SizeType InId;
  H_FIFO_SizeType OutId;
  H_FIFO_SizeType BufferSize;
  H_FIFO_SizeType EmptySize;


  InId=fifo->FIFO.InId;
  OutId=fifo->FIFO.OutId;
  BufferSize=fifo->FIFO.BufferSize;

  //计算空间
  if(InId<OutId){
    EmptySize=OutId-InId;
  }else{
    EmptySize=BufferSize-InId;
    if(EmptySize<OutId){
      EmptySize=OutId;
    }
  }

  EmptySize-=fifo->FIFO.SizeSize;//去掉用于表示长度的大小

  return EmptySize;
}

/**
 * @brief 向FIFO中添加包
 * @param fifo FIFO句柄
 * @param Data 要添加的数据
 * @param Length 长度(以fifo输入的数据类型位宽为单位)
 * @return 0:成功 其他:失败 空间不足
 */
int H_FIFO_Write(H_FIFO* fifo,const void* Data,H_FIFO_SizeType Length){
  H_FIFO_SizeType InId;
  H_FIFO_SizeType OutId;
  H_FIFO_SizeType BufferSize;
  H_FIFO_SizeType SizeSize;
  H_FIFO_SizeType Empty;
  H_FIFO_SizeType i;
  volatile void* Buffer;


  InId=fifo->FIFO.InId;
  OutId=fifo->FIFO.OutId;
  BufferSize=fifo->FIFO.BufferSize;
  SizeSize=fifo->FIFO.SizeSize;

  Length+=SizeSize;
  
  i=BufferSize-InId;

  if(InId<OutId){
    Empty=OutId-InId;
    if(Empty<=Length){//等于也不行 满的情况与空的情况 I O 都为0 为避免混淆不能把FIFO填满
      return -1;
    }
  }else{
    Empty=i;
    if(Empty<=Length){//判断是否可能出现溢出情况
      if(Empty==Length){//刚好能填满后半部分
        if(OutId==0){//前半无空间, 不能让后半部分填满
          return -1;
        }
      }else{//Empty<Length 
        Empty=OutId;
        if(Empty<=Length){//等于也不行 满的情况与空的情况 I O 都为0 为避免混淆不能把FIFO填满
          return -1;
        }
      }
    }
  }

  //如果到此处 说明肯定可写入 要不从0写入要不从fifo->Buffer_InId写入

  //装填数据
  Buffer=fifo->FIFO.Buffer;
  //判断从0写入还是从fifo->Buffer_InId写入
  if(i<Length){
    //从0写入

    if(i>=SizeSize){
      //标记
      fifo->WriteSize(Buffer,InId,0);
    }

    //标记
    fifo->WriteSize(Buffer,0,Length);

    InId=0;
    
  }else{
    //从I写入

    //标记
    fifo->WriteSize(Buffer,InId,Length);

  }

  i=SizeSize;
  fifo->Copy(Buffer,InId+i,(const volatile void*)Data,Length-i);

  InId+=Length;
  if(InId==BufferSize){
    InId=0;
  }
  fifo->FIFO.InId=InId;

  return 0;
}

/**
 * @brief 向FIFO中添加包(头部插入一个数据)
 * @param fifo FIFO句柄
 * @param Data0 头部插入的数据(位宽与fifo输入的数据类型一致)
 * @param Data 要添加的数据
 * @param Length 长度(以fifo输入的数据类型位宽为单位)
 * @return 0:成功 其他:失败 空间不足
 */
int H_FIFO_Write_Data0(H_FIFO* fifo,const void* Data0,const void* Data,H_FIFO_SizeType Length){
  H_FIFO_SizeType InId;
  H_FIFO_SizeType OutId;
  H_FIFO_SizeType BufferSize;
  H_FIFO_SizeType SizeSize;
  H_FIFO_SizeType Empty;
  H_FIFO_SizeType i;
  volatile void* Buffer;


  InId=fifo->FIFO.InId;
  OutId=fifo->FIFO.OutId;
  BufferSize=fifo->FIFO.BufferSize;
  SizeSize=fifo->FIFO.SizeSize;

  Length+=SizeSize+1;
  
  i=BufferSize-InId;
  
  if(InId<OutId){
    Empty=OutId-InId;
    if(Empty<=Length){//等于也不行 满的情况与空的情况 I O 都为0 为避免混淆不能把FIFO填满
      return -1;
    }
  }else{
    Empty=i;
    if(Empty<=Length){//判断是否可能出现溢出情况
      if(Empty==Length){//刚好能填满后半部分
        if(OutId==0){//前半无空间, 不能让后半部分填满
          return -1;
        }
      }else{//Empty<Length 
        Empty=OutId;
        if(Empty<=Length){//等于也不行 满的情况与空的情况 I O 都为0 为避免混淆不能把FIFO填满
          return -1;
        }
      }
    }
  }

  //如果到此处 说明肯定可写入 要不从0写入要不从fifo->Buffer_InId写入

  //装填数据
  Buffer=fifo->FIFO.Buffer;
  //判断从0写入还是从fifo->Buffer_InId写入
  if(i<Length){
    //从0写入

    if(i>=SizeSize){
      //标记
      fifo->WriteSize(Buffer,InId,0);
    }

    //标记
    fifo->WriteSize(Buffer,0,Length);
    fifo->Copy(Buffer,SizeSize,(const volatile void*)Data0,1);

    InId=0;
    
  }else{
    //从I写入

    //标记
    fifo->WriteSize(Buffer,InId,Length);
    fifo->Copy(Buffer,InId+SizeSize,(const volatile void*)Data0,1);

  }

  i=SizeSize+1;
  fifo->Copy(Buffer,InId+i,(const volatile void*)Data,Length-i);

  InId+=Length;
  if(InId==BufferSize){
    InId=0;
  }
  fifo->FIFO.InId=InId;

  return 0;
}

/**
 * @brief 读取输出数据指针 处理完数据后 调用H_FIFO_Next()来释放读取到的数据包
 * @param fifo FIFO句柄
 * @param LengthPtr 用于返回数据包大小
 * @return 读取数据的指针 如果为NULL((void*)0)表示无可用数据
 */
const void* H_FIFO_Read(H_FIFO* fifo,H_FIFO_SizeType* LengthPtr){
  H_FIFO_SizeType OutId;
  H_FIFO_SizeType BufferSize;
  H_FIFO_SizeType SizeSize;
  H_FIFO_SizeType Size;
  volatile void* Buffer;


  OutId=fifo->FIFO.OutId;
  if(fifo->FIFO.InId==OutId){
    LengthPtr[0]=0;
    return NULL;
  }

  BufferSize=fifo->FIFO.BufferSize;
  SizeSize=fifo->FIFO.SizeSize;
  Buffer=fifo->FIFO.Buffer;

  if((BufferSize-OutId)<SizeSize){
    OutId=0;
    fifo->FIFO.OutId=0;

    Size=fifo->ReadSize(Buffer,OutId);
  }else{
    Size=fifo->ReadSize(Buffer,OutId);

    if(Size<SizeSize){//末尾被跳过的一段空间
      OutId=0;
      fifo->FIFO.OutId=0;

      Size=fifo->ReadSize(Buffer,OutId);
    }
  }

  LengthPtr[0]=Size-SizeSize;
  return fifo->GetPointer(Buffer,OutId+SizeSize);
}

/**
 * @brief 读取数据指针切换到下一个 (必须在FIFO中有数据时使用, 即H_FIFO_Read()能调用成功的情况下)
 * @param fifo FIFO句柄
 * @return 无
 */
void H_FIFO_Next(H_FIFO* fifo){
  H_FIFO_SizeType OutId;
  H_FIFO_SizeType BufferSize;
  H_FIFO_SizeType SizeSize;
  H_FIFO_SizeType Size;
  volatile void* Buffer;

  
  OutId=fifo->FIFO.OutId;
  BufferSize=fifo->FIFO.BufferSize;
  SizeSize=fifo->FIFO.SizeSize;
  Buffer=fifo->FIFO.Buffer;

  if((BufferSize-OutId)<SizeSize){
    OutId=0;

    Size=fifo->ReadSize(Buffer,OutId);
  }else{
    Size=fifo->ReadSize(Buffer,OutId);

    if(Size<SizeSize){//末尾被跳过的一段空间
      OutId=0;

      Size=fifo->ReadSize(Buffer,OutId);
    }
  }

  OutId+=Size;
  if(OutId==BufferSize){
    fifo->FIFO.OutId=0;
  }else{
    fifo->FIFO.OutId=OutId;
  }

}



